package com.sure0000.basic.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Java动态代理机制的出现，使得Java开发人员不用手工编写代理类，只要简单地制定一组接口及委托类对象，便能动态地获得代理类。
 * 代理类会负责将所有的方法调用分配到委托对象上反射执行，配置执行过程中，开发人员还可以进行修改。
 *
 * 缺点：
 * Proxy只能对interface进行代理，无法实现对class的动态代理。观察动态生成的代理继承关系图可知原因，
 * 他们已经有一个固定的父类叫做Proxy，Java语法限定其不能再继承其他的父类
 * @author xuyouchang
 * Created on 2021/4/1.
 */
public class DynamicProxy {
    public static void main(String[] args) {
        //设置这个值，在程序运行完成后，可以生成代理类
//        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        IHello hello = (IHello) new DynamicProxyTest().bind(new Hello());
        hello.sayHello();
        hello.sayHello2();
    }

    interface IHello {
        void sayHello();
        void sayHello2();
    }

    static class Hello implements IHello {
        public void sayHello() {
            System.out.println("hello world 01");
        }

        public void sayHello2() {
            System.out.println("hello world 02");
        }
    }

    static class DynamicProxyTest implements InvocationHandler {
        Object originalObj;

        Object bind(Object originalObj) {
            this.originalObj = originalObj;
            return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),
                    originalObj.getClass().getInterfaces(), this);
        }

        // 将在接口每个函数执行前输出 Welcome
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before");
            method.invoke(originalObj, args);
            System.out.println("after");
            return null;
        }
    }
}
